#include "gobang.h"


GoBang::GoBang(){

    //窗口初始化
    this->show(); //显示窗口
    this->setWindowTitle("五子棋"); //设置窗口名称
    this->setFixedSize(600,700); //改变窗口大小，并且锁定大小

    QMediaPlayer *startSound=new QMediaPlayer(this);
    startSound->setMedia(QUrl("qrc:/new/prefix1/群星 - 望江南.mp3.mp3"));
    startSound->setVolume(90);
    startSound->play();


    //初始化部分数据
    undo_button.resize(100, 30); //设置按钮的大小
    undo_button.setParent(this); //将按钮放置到窗口中
    undo_button.move(270, 35);  //放置位置
    undo_button.setText("悔棋"); //设置按钮标签
    undo_button.show();
    //按钮按下信号连接槽函数
    connect(&undo_button, &QPushButton::clicked, this, &GoBang::undoFunction);

    abandon_button.resize(100, 30); //设置按钮的大小
    abandon_button.setParent(this); //将按钮放置到窗口中
    abandon_button.move(380, 35);  //放置位置
    abandon_button.setText("让子"); //设置按钮标签
    abandon_button.show();
    connect(&abandon_button, &QPushButton::clicked, this, &GoBang::abandonFunction);

    reset_button.resize(100, 30); //设置按钮的大小
    reset_button.setParent(this); //将按钮放置到窗口中
    reset_button.move(490, 35);  //放置位置
    reset_button.setText("重置"); //设置按钮标签
    reset_button.show();
    connect(&reset_button, &QPushButton::clicked, this, &GoBang::resetFunction);
    //开启跟踪鼠标
    this->setMouseTracking(true);
}


//让子
void GoBang::abandonFunction(){
    indicate.setType(!indicate.getType());
}

//悔棋
void GoBang::undoFunction(){
    if(pieces.size() > 0){
        indicate.setType(!indicate.getType());
        pieces.erase(pieces.begin() + (pieces.size() - 1));
        update();
    }
}

//重新开始
void GoBang::resetFunction(){
    pieces.clear();
}
//绘制画板
void GoBang::displayBoard(){
    QPainter painter(this);
    QPen pen; //画笔
    QBrush brush;   //画刷
    pen.setColor(Qt::black); //设置画笔颜色
    pen.setWidth(2); //设置线宽
    brush.setColor(QColor(200, 200, 169, 255)); //设置画刷颜色
    brush.setStyle(Qt::SolidPattern); //设置画刷样式
    painter.setPen(pen);
    painter.setBrush(brush);
    painter.drawLine(0,100,600,100);
    painter.drawRect(0, 100, 600, 600);
    brush.setColor(QColor(131, 175, 155, 255)); //设置画刷颜色
    painter.setBrush(brush);
    painter.drawRect(0, 0, 600, 100);
    //绘制边框
    painter.drawLine(50,150,550,150);
    painter.drawLine(50,650,550,650);
    painter.drawLine(50,150,50,650);
    painter.drawLine(550,150,550,650);
    //绘制横线
    for(int i = 150; i <= 650; i += 25){
        painter.drawLine(50,i,550,i);
    }
    //绘制竖线
    for(int i = 50; i <= 550; i += 25){
        painter.drawLine(i,150,i,650);
    }
    //绘制下棋的点标记
    brush.setColor(Qt::black); //设置画刷颜色
    painter.setBrush(brush);
    for(int i = 50; i <= 550; i += 25){
        for(int j = 150; j <= 650; j += 25){
            painter.drawRect(i - 2, j - 2, 4, 4);
        }
    }
}
//绘制棋子
void GoBang::displayPieces(){
    for(unsigned int i = 0; i < pieces.size(); i++){
        QPainter painter(this);
        QPen pen;
        QBrush brush;
        brush.setStyle(Qt::SolidPattern); //设置画刷样式
        if(pieces[i].getType()){
            pen.setColor(Qt::transparent); //设置画笔颜色
            brush.setColor(Qt::black);
        }
        else{
            pen.setColor(Qt::transparent); //设置画笔颜色
            brush.setColor(Qt::white);
        }
        painter.setPen(pen);
        painter.setBrush(brush);
        painter.drawEllipse(pieces[i].getY()*25 + 50 - 12.5, pieces[i].getX()*25 + 150- 12.5, 12.5 * 2, 12.5 * 2);
    }//画圆
}

void GoBang::paintEvent(QPaintEvent * event){
    displayBoard();
    displayPieces();
    showText(); //显示落子提示
}

void GoBang::mouseMoveEvent(QMouseEvent *event){
    //获取鼠标坐标
    indicate.setX(event->pos().x());
    indicate.setY(event->pos().y());
    update();
}

void GoBang::mousePressEvent(QMouseEvent *event){
    if(event->button()==Qt::LeftButton)
    {
        indicate.setX(event->pos().x());
        indicate.setY(event->pos().y());
        if(
                (indicate.getX() >= 50)&&
                (indicate.getX() < 550)&&
                (indicate.getY() >= 150)&&
                (indicate.getY() < 650)
                ){
            int y =(indicate.getX() -50 + 12.5) /25;
            int x =(indicate.getY() -150 + 12.5) /25;
            Piece add_piece;
            add_piece.setX(x);
            add_piece.setY(y);
            add_piece.setType(indicate.getType());
            if(!pieceIfExist(add_piece)){
                pieces.push_back(add_piece);
                indicate.setType(!indicate.getType());
                update();
                int over_flag = ifOver();
                if(over_flag != 0){
                    QString show = "";
                    if(over_flag == 1){
                        show = "白棋赢了";
                    }
                    else{
                        show = "黑棋赢了";
                    }
                    QMessageBox::information(this,"游戏结束",show);
                    //新的游戏进行数据初始化
                    pieces.clear();
                    indicate.setType(false);
                }
            }
        }
    }
}

bool GoBang::pieceIfExist(Piece a_piece){
    bool result = false;
    for(unsigned int i = 0; i < pieces.size(); i++){
         if(
                 pieces[i].getX() == a_piece.getX()&&
                 pieces[i].getY() == a_piece.getY()
                 )
         {
             result = true;
             break;
         }
    }
    return result;
}

int GoBang::ifOver(){
    int board_infor[21][21]; //获取棋盘落子信息，0为空1为白，2为黑
    for(int i = 0; i< 21; i++){
        for(int j = 0; j < 21;j++){
            board_infor[i][j] = 0;
        }
    }
    //获取所有棋子的信息
    for(unsigned int i = 0; i < pieces.size(); i++){
        board_infor[pieces[i].getX()][pieces[i].getY()] = pieces[i].getType() + 1;
    }

    //判断四个方向是否有五子连珠的情况
    //判断横竖情况
    for(int i = 0; i< 21; i++){
        int num = 0;
        int type = board_infor[i][0];
        for(int j = 0; j < 21;j++){
            if(board_infor[i][j] == type){
                num++;
            }
            else{
                num = 1;
                type = board_infor[i][j];
            }
            if((num == 5)&&(type != 0)){
                return type;
            }
        }
        num = 0;
        type = board_infor[0][i];
        for(int j = 0; j < 21;j++){
            if(board_infor[j][i] == type){
                num++;
            }
            else{
                num = 1;
                type = board_infor[j][i];
            }
            if((num == 5)&&(type != 0)){
                return type;
            }
        }
    }
    //判断斜着的情况
    for(int i = 0; i< 21; i++){
        int num = 0;
        int type = board_infor[0][i];
        for(int k = i, j = 0; j < 21 - i;j++, k++){
            if(board_infor[j][k] == type){
                num++;
            }
            else{
                num = 1;
                type = board_infor[j][k];
            }
            if((num == 5)&&(type != 0)){
                return type;
            }
        }

        num = 0;
        type = board_infor[i][0];
        for(int k = i, j = 0; j < 21 - i;j++, k++){
            if(board_infor[k][j] == type){
                num++;
            }
            else{
                num = 1;
                type = board_infor[k][j];
            }
            if((num == 5)&&(type != 0)){
                return type;
            }
        }

        num = 0;
        type = board_infor[0][i];
        for(int k = i, j = 0; j <= i;j++, k--){
            if(board_infor[j][k] == type){
                num++;
            }
            else{
                num = 1;
                type = board_infor[j][k];
            }
            if((num == 5)&&(type != 0)){
                return type;
            }
        }

        num = 0;
        type = board_infor[i][20];
        for(int k = i, j = 20; j >= i;j--, k++){
            if(board_infor[k][j] == type){
                num++;
            }
            else{
                num = 1;
                type = board_infor[k][j];
            }
            if((num == 5)&&(type != 0)){
                return type;
            }
        }
    }
    return 0;
}

void GoBang::showText(){
    QPainter painter(this);
    QPen pen;
    QFont font("楷体", 20, QFont::Bold, true);
    pen.setColor(Qt::black); //设置画笔颜色
    painter.setPen(pen);
    painter.setFont(font);
    QRect rectangle = QRect(0, 0, 290, 100);
    if(indicate.getType()){
        painter.drawText(rectangle, Qt::AlignCenter, "黑棋落子");
    }
    else{
        painter.drawText(rectangle, Qt::AlignCenter, "白棋落子");
    }
}
